package com.xteam.ecsystem.dao.Impl;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigInteger;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.hibernate.type.TypeFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;

import com.tangkf.utils.CommonUtils;
import com.xteam.ecsystem.dao.BaseDao;
import com.xteam.ecsystem.dao.page.Page;
import com.xteam.ecsystem.dao.page.PageObjectSet;
import com.xteam.ecsystem.utils.PageCenterStation;

@SuppressWarnings("unchecked")
public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
	
	private static final Log LOG = LogFactory.getLog(BaseDaoImpl.class);
	protected SessionFactory sessiones;

	public List<T> findAll(Class<T> clazz) throws HibernateException {
		return criteriaPageObjectSet(clazz, null, null, -1, -1, false)
				.getResultList();
	}

	public List<Object> queryHqlIn(String hql, List listin) {
		Query query = getSession().createQuery(hql);
		query.setParameterList("alist", listin);
		return query.list();
	}

	/**
	 * @see com.xuming.dao.BaseDao#findToPageObjectSet(java.lang.Class, int,
	 *      int)
	 * @author yuanjie.wu
	 */
	public PageObjectSet<T> findToResult(Class<T> clazz, int first, int max)
			throws HibernateException {
		return criteriaPageObjectSet(clazz, null, null, first, max, true);
	}

	/**
	 * @see com.xuming.dao.BaseDao#findAllByOrders(java.lang.Class,
	 *      org.hibernate.criterion.Order[])
	 * @author yuanjie.wu
	 */
	public List<T> findAllByOrders(Class<T> clazz, Order[] orders)
			throws HibernateException {
		return criteriaPageObjectSet(clazz, null, orders, -1, -1, false)
				.getResultList();
	}

	/**
	 * @see com.xuming.dao.BaseDao#findAllByCriterions(java.lang.Class,
	 *      org.hibernate.criterion.Criterion[])
	 * @author yuanjie.wu
	 */
	public List<T> findAllByCriterions(Class<T> clazz,
			Criterion[] criterions) throws HibernateException {
		return criteriaPageObjectSet(clazz, criterions, null, -1, -1, false)
				.getResultList();
	}

	/**
	 * @see com.xuming.dao.BaseDao#findToPageObjectSet(java.lang.Class,
	 *      org.hibernate.criterion.Criterion[], int, int)
	 * @author yuanjie.wu
	 */
	public PageObjectSet<T> findToResult(Class<T> clazz,
			Criterion[] criterions, int first, int max)
			throws HibernateException {
		return criteriaPageObjectSet(clazz, criterions, null, first, max, true);
	}

	/**
	 * @see com.xuming.dao.BaseDao#findAllByCriteronsAndOrders(java.lang.Class,
	 *      org.hibernate.criterion.Criterion[],
	 *      org.hibernate.criterion.Order[])
	 * @author yuanjie.wu
	 */
	public List<T> findAllByCriteronsAndOrders(Class<T> clazz,
			Criterion[] criterions, Order[] orders) throws HibernateException {
		return criteriaPageObjectSet(clazz, criterions, orders, -1, -1, false)
				.getResultList();
	}

	/**
	 * @see com.xuming.dao.BaseDao#findToPageObjectSet(java.lang.Class,
	 *      org.hibernate.criterion.Criterion[],
	 *      org.hibernate.criterion.Order[], int, int)
	 * @author yuanjie.wu
	 */
	public PageObjectSet<T> findToResult(Class<T> clazz,
			Criterion[] criterions, Order[] orders, int first, int max)
			throws HibernateException {
		return criteriaPageObjectSet(clazz, criterions, orders, first, max,
				true);
	}

	protected PageObjectSet<T> criteriaPageObjectSet(Class<T> clazz,
			Criterion[] criterions, Order[] orders, int first, int max,
			boolean doPager) throws HibernateException {
		Criteria criteria = getSession().createCriteria(clazz);

		// 设置查询条件
		for (int i = 0; criterions != null && i < criterions.length; i++) {
			criteria.add(criterions[i]);
		}

		// 设置排序
		for (int i = 0; orders != null && i < orders.length; i++) {
			criteria.addOrder(orders[i]);
		}

		long rowCount = 0;

		// 分页处理
		if (doPager) {
			criteria.setProjection(Projections.rowCount());
			rowCount = ((Integer) criteria.uniqueResult()).longValue();// 查询获取数据的总量
			criteria.setProjection(null);// 清除criteria对象中的查询函数

			if (first >= 0 && (max > 0 && max >= first)) {
				criteria.setFirstResult(first);
				criteria.setMaxResults(max);
			}
		}

		List<T> reusltList = (List<T>) criteria.list();

		PageObjectSet<T> pos = new PageObjectSet<T>();
		pos.setResultList(reusltList);
		pos.setRowCount(rowCount);

		return pos;
	}

	/**
	 * @see com.xuming.dao.BaseDao#save(java.lang.Object)
	 */
	public void save(Object obj) {
		try {
			getHibernateTemplate().save(obj);
			// getHibernateTemplate().flush();
		} catch (DataAccessException e) {
			LOG.error("添加信息出错！", e);
			throw new HibernateException(e);
		} catch (Exception e) {
			LOG.error("添加信息出错！", e);

		}
	}

	/**
	 * @see com.xuming.dao.BaseDao#batchSave(java.util.Collection)
	 * @author yuanjie.wu
	 */
	public void batchSave(final Collection<Object> objects)
			throws HibernateException {
		Assert.notNull(objects);

		try {
			getHibernateTemplate().execute(new HibernateCallback() {
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
					for (Object object : objects) {
						session.save(object);
					}
					return null;
				}
			});
		} catch (DataAccessException e) {
			LOG.error("批量保存操作失败", e);
			throw new HibernateException(e);
		}
	}

	/**
	 * @see com.xuming.dao.BaseDao#batchSave(java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public void batchSave(Object[] objects) throws HibernateException {
		batchSave(Arrays.asList(objects));
	}
	
	/**
	 * @see com.xuming.dao.BaseDao#batchUpdate(java.lang.Object[])
	 */
	public void batchUpdate(Object[] objects) throws HibernateException {
		batchUpdate(Arrays.asList(objects));
	}
	
	/**
	 * @see com.xuming.dao.BaseDao#batchUpdate(java.util.Collection)
	 */
	public void batchUpdate(final Collection<Object> objects)
			throws HibernateException {
		Assert.notNull(objects);

		try {
			getHibernateTemplate().execute(new HibernateCallback() {
				@Override
				public Object doInHibernate(Session session)
						throws HibernateException, SQLException {
					for (Object object : objects) {
						session.update(object);
					}
					return null;
				}
			});
		} catch (DataAccessException e) {
			LOG.error("批量更新操作失败", e);
			throw new HibernateException(e);
		}
	}

	/**
	 * @see com.xuming.dao.BaseDao#saveOrUpdate(java.lang.Object)
	 */
	public void saveOrUpdate(Object obj) throws HibernateException {
		try {
			getHibernateTemplate().saveOrUpdate(obj);
		} catch (DataAccessException e) {
			LOG.error(obj.getClass().getName() + "对象保存或更新操作失败", e);
			throw new HibernateException(e);
		}
	}

	/**
	 * @see com.xuming.dao.BaseDao#update(java.lang.Object)
	 */
	public void update(Object obj) throws HibernateException {
		try {
			getHibernateTemplate().update(obj);
		} catch (DataAccessException e) {
			LOG.error(obj.getClass().getName() + "对象更新操作失败", e);
			throw new HibernateException(e);
		}
	}

	/**
	 * @see com.xuming.dao.BaseDao#delete(java.lang.Object)
	 */
	public void delete(Object obj) throws HibernateException {
		try {
			getHibernateTemplate().delete(obj);
		} catch (DataAccessException e) {
			LOG.error(obj.getClass().getName() + "对象删除操作失败", e);
			throw new HibernateException(e);
		}
	}

	/**
	 * @see com.xuming.dao.BaseDao#get(java.lang.Class, java.io.Serializable)
	 */
	public Object get(Class<?> classz, Serializable pk)
			throws HibernateException {
		Object obj = null;
		obj = getHibernateTemplate().get(classz, pk);
		if (obj == null) {
			return null;
		} else {
			getHibernateTemplate().initialize(obj);
		}
		return obj;
	}

	/**
	 * @see com.xuming.dao.BaseDao#find(java.lang.String)
	 */
	public List<?> find(String hql) throws HibernateException {
		return getHibernateTemplate().find(hql);
	}

	/**
	 * @see com.xuming.dao.BaseDao#find(java.lang.String, java.lang.Object)
	 */
	public List<?> find(String hql, Object param) throws HibernateException {
		return getHibernateTemplate().find(hql, param);
	}

	/**
	 * @see com.xuming.dao.BaseDao#find(java.lang.String, java.lang.Object[])
	 */
	public List<?> find(String hql, Object[] params) throws HibernateException {
		return getHibernateTemplate().find(hql, params);
	}

	/**
	 * @see com.xuming.dao.BaseDao#findObject(java.lang.String,
	 *      java.lang.Object[])
	 */
	public Object findObject(String hql, Object[] params)
			throws HibernateException {
		List<?> list = find(hql, params);
		if (list != null && list.size() > 0)
			return (Object) list.get(0);
		return null;
	}

	/**
	 * @see com.xuming.dao.BaseDao#deleteAll(java.util.Collection)
	 * @author yuanjie.wu
	 */
	public void deleteAll(Collection<?> c) throws HibernateException {
		getHibernateTemplate().deleteAll(c);
	}

	/**
	 * @see com.xuming.dao.BaseDao#saveOrUpdateAll(java.util.Collection)
	 * @author yuanjie.wu
	 */
	public void saveOrUpdateAll(Collection<?> c) throws HibernateException {
		getHibernateTemplate().saveOrUpdateAll(c);
	}

	/**
	 * @see com.xuming.dao.BaseDao#findByProperty(java.lang.String,
	 *      java.lang.String, java.lang.Object)
	 */
	public List<?> findByProperty(String hql, String propertyName, Object value)
			throws HibernateException {
		return getHibernateTemplate()
				.findByNamedParam(hql, propertyName, value);
	}

	/**
	 * @see com.xuming.dao.BaseDao#query(java.lang.String, java.lang.String[],
	 *      java.lang.Object[])
	 */
	public List<?> query(String hql, String[] paramNames, Object[] values)
			throws HibernateException {
		return getHibernateTemplate().findByNamedParam(hql, paramNames, values);
	}

	/**
	 * @see com.xuming.dao.BaseDao#query(java.lang.String, java.lang.String,
	 *      int, int)
	 * @author yuanjie.wu （内部做调整）
	 */
	public PageObjectSet<?> query(final String countHQL, final String hql,
			final int first, final int max) throws HibernateException {
		return (PageObjectSet<?>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query countQuery = session.createQuery(countHQL);
						long count = (Long) countQuery.uniqueResult();

						Query query = session.createQuery(hql);
						query.setFirstResult(first);
						query.setMaxResults(max);

						List<Object> list = (List<Object>) query.list();

						return new PageObjectSet<Object>(count, list);
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#query(java.lang.String, java.lang.String,
	 *      java.lang.Object[], int, int)
	 * @author yuanjie.wu （内部做调整）
	 */
	public List<Object> queryHqlLis(final String hql, final Object[] args)
			throws HibernateException {
		return (List<Object>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session) {
						Query query = session.createQuery(hql);
						for (int i = 0; args != null && i < args.length; i++) {
							query.setParameter(i, args[i]);
						}
						List<Object> list = (List<Object>) query.list();
						return list;
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#query(java.lang.String, java.lang.String,
	 *      java.lang.Object[], int, int)
	 * @author yuanjie.wu （内部做调整）
	 */
	public PageCenterStation<?> queryList(final String countHQL,
			final String hql, final Object[] args, final int first,
			final int max) throws HibernateException {
		return (PageCenterStation<?>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query countQuery = session.createQuery(countHQL);
						for (int i = 0; args != null && i < args.length; i++) {
							countQuery.setParameter(i, args[i]);
						}

						long count = (Long) countQuery.uniqueResult();

						Query query = session.createQuery(hql);
						for (int i = 0; args != null && i < args.length; i++) {
							query.setParameter(i, args[i]);
						}
						if (first != -1 && max != -1) {
							query.setFirstResult(first);
							query.setMaxResults(max);
						}

						List<Object> list = (List<Object>) query.list();

						return new PageCenterStation<Object>(count, list);
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#query(java.lang.String, java.lang.String,
	 *      java.lang.String[], java.lang.Object[], int, int)
	 * @author yuanjie.wu （内部做调整）
	 */
	public PageObjectSet<?> query(final String countHQL, final String hql,
			final String[] params, final Object[] args, final int first,
			final int max) throws HibernateException {
		return (PageObjectSet<?>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query countQuery = session.createQuery(countHQL);
						for (int i = 0; params != null && args != null
								&& params.length != args.length
								&& i < params.length; i++) {
							countQuery.setParameter(params[i], args[i]);
						}

						long count = (Long) countQuery.uniqueResult();

						Query query = session.createQuery(hql);
						for (int i = 0; params != null && args != null
								&& params.length != args.length
								&& i < params.length; i++) {
							query.setParameter(params[i], args[i]);
						}
						query.setFirstResult(first);
						query.setMaxResults(max);

						List<Object> list = (List<Object>) query.list();

						return new PageObjectSet<Object>(count, list);
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#count(java.lang.String)
	 * @author yuanjie.wu
	 */
	public Long count(String hql) throws HibernateException {
		Long countData = ((Long) getHibernateTemplate().find(hql).get(0))
				.longValue();
		return countData;
	}

	/**
	 * @see com.xuming.dao.BaseDao#count(java.lang.String, java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public Long count(final String hql, Object[] args)
			throws HibernateException {
		Long countData = ((Long) getHibernateTemplate().find(hql, args).get(0))
				.longValue();
		return countData;
	}

	/**
	 * @see com.xuming.dao.BaseDao#executeUpdate(java.lang.String)
	 * @author yuanjie.wu
	 */
	public int executeUpdate(String hql) throws HibernateException {
		return executeUpdate(hql, null);
	}

	/**
	 * @see com.xuming.dao.BaseDao#executeUpdate(java.lang.String,
	 *      java.lang.Object[])
	 */
	public int executeUpdate(final String hql, final Object[] objs)
			throws HibernateException {
		return executeUpdate(hql, null, objs);
	}

	/**
	 * @see com.xuming.dao.BaseDao#executeUpdate(java.lang.String,
	 *      java.lang.String[], java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public int executeUpdate(final String hql, final String[] params,
			final Object[] objs) throws HibernateException {
		return (Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Query query = session.createQuery(hql);
						if (params != null && objs != null) {
							if (params.length != objs.length)
								return -1;
							for (int i = 0; i < objs.length; i++) {
								query.setParameter(params[i], objs[i]);
							}
						} else if (params == null && objs != null) {
							for (int i = 0; i < objs.length; i++) {
								query.setParameter(i, objs[i]);
							}
						}
						return query.executeUpdate();
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#deleteByNamedParam(java.lang.String,
	 *      java.lang.String, java.io.Serializable[])
	 * @author yuanjie.wu
	 */
	public int deleteByNamedParam(String hql, String param,
			final Serializable[] value) throws HibernateException {
		return deleteByNamedParams(hql, new String[] { param },
				new ArrayList<Serializable[]>() {
					private static final long serialVersionUID = -1949433476774921543L;
					{
						add(value);
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#deleteByNamedParams(java.lang.String,
	 *      java.lang.String[], java.util.List)
	 * @author yuanjie.wu
	 */
	public int deleteByNamedParams(final String hql, final String[] params,
			final List<Serializable[]> list) throws HibernateException {
		if (params.length != list.size())
			return -1;

		System.err.println("--->" + params[0] + "--->" + list.get(0)[0]);

		return (Integer) getHibernateTemplate().executeWithNewSession(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query query = session.createQuery(hql);
						int idx = 0;
						for (Serializable[] ser : list) {
							query.setParameterList(params[idx], ser);
							idx++;
						}
						return query.executeUpdate();
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#countWithSQL(java.lang.String,
	 *      java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public Long countWithSQL(String sql, Object... objs)
			throws HibernateException {
		return countWithSQL(sql, null, objs);
	}

	/**
	 * @see com.xuming.dao.BaseDao#countWithSQL(java.lang.String,
	 *      java.lang.String[], java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public Long countWithSQL(final String sql, final String[] params,
			final Object[] objs) throws HibernateException {
		return (Long) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql);
				for (int i = 0; params != null && objs != null
						&& params.length == objs.length && i < params.length; i++) {
					query.setParameter(params[i], objs[i]);
				}

				for (int i = 0; params == null && objs != null
						&& i < objs.length; i++) {
					query.setParameter(i + 1, objs[i]);
				}

				return (Long) query.uniqueResult();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#countWithAggFunSQL(java.lang.String, java.lang.Object[])
	 */
	public BigInteger countWithAggFunSQL(final String sql, final Object[] objs) 
			throws HibernateException {
		return (BigInteger) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql);
				
				for (int i = 0; objs != null && i < objs.length; i++) {
					query.setParameter(i + 1, objs[i]);
				}

				return (BigInteger) query.uniqueResult();
			}
		});
	}

	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#countWithSQLForObjVal(java.lang.String, java.lang.String[], java.lang.Object[])
	 */
	public Object countWithSQLForObjVal(final String sql, final String[] params,
			final Object[] objs) throws HibernateException {
		return (Object) getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql);
				for (int i = 0; params != null && objs != null
						&& params.length == objs.length && i < params.length; i++) {
					query.setParameter(params[i], objs[i]);
				}

				for (int i = 0; params == null && objs != null
						&& i < objs.length; i++) {
					query.setParameter(i + 1, objs[i]);
				}
				return query.uniqueResult();
			}
		});
	}

	public int executeUpdateWithSQL(final String sql, final Object... objs) {

		return executeUpdateWithSQL(sql, null, objs);
	}

	/**
	 * @see com.xuming.dao.BaseDao#executeUpdateWithSQL(java.lang.String,
	 *      java.lang.String[], java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public int executeUpdateWithSQL(final String sql, final String[] params,
			final Object[] objs) {
		return (Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						SQLQuery query = session.createSQLQuery(sql);
						for (int i = 0; params != null && objs != null
								&& params.length == objs.length
								&& i < params.length; i++) {
							query.setParameter(params[i], objs[i]);
						}

						for (int i = 0; params == null && objs != null
								&& i < objs.length; i++) {
//							query.setParameter(i + 1, objs[i]);
							
							// sqlQuery索引是从0开始
							query.setParameter(i, objs[i]);
						}

						return query.executeUpdate();
					}
				});
	}

	/**
	 * @see com.xuming.dao.BaseDao#queryWithSQL(java.lang.Class,
	 *      java.lang.String, java.lang.String[], java.lang.Object[])
	 * @author yuanjie.wu
	 */
	public List<T> queryWithSQL(final Class<T> clazz, final String sql,
			final String[] params, final Object[] objs)
			throws HibernateException {
		return (List<T>) getHibernateTemplate().executeFind(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						SQLQuery query = session.createSQLQuery(sql);
						for (int i = 0; params != null && objs != null
								&& params.length == objs.length
								&& i < params.length; i++) {
							query.setParameter(params[i], objs[i]);
						}

						for (int i = 0; params == null && objs != null
								&& i < objs.length; i++) {
							// query.setParameter(i + 1, objs[i]);
							
							// sqlQuery索引是从0开始
							query.setParameter(i, objs[i]);
						}

						if (clazz.equals(Map.class))
							query
									.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
						else if (clazz.equals(List.class))
							query.setResultTransformer(Transformers.TO_LIST);
						else
							query.setResultTransformer(Transformers
									.aliasToBean(clazz));

						return query.list();
					}
				});
	}
/*
	public <T> PageObjectSet<T> queryWithSQL(Class<T> clazz, String countSql,
			String sql, int first, int max) throws HibernateException {
		return queryWithSQL(clazz, countSql, sql, null, null, first, max, true);
	}

	public <T> PageObjectSet<T> queryWithSQL(Class<T> clazz, String countSql,
			String sql, Object[] objs, int first, int max)
			throws HibernateException {
		return queryWithSQL(clazz, countSql, sql, null, objs, first, max, true);
	}
*/
	public PageCenterStation<?> queryWithSQL(final Class<T> clazz,
			final String countSql, final String sql, final String[] params,
			final Object[] objs, final int first, final int max)
			throws HibernateException {
		return queryWithSQL(clazz, countSql, sql, params, objs, first, max,
				true);
	}

	/**
	 * 分页查询
	 * 
	 * @author tangkf
	 * @param <T>
	 * @param clazz
	 * @param countSql
	 * @param sql
	 * @param params
	 * @param objs
	 * @param first
	 * @param max
	 * @param isExecuteCountSql
	 * @return
	 * @throws HibernateException
	 */
	protected PageCenterStation<?> queryWithSQL(final Class<T> clazz,
			final String countSql, final String sql, final String[] params,
			final Object[] objs, final int first, final int max,
			final boolean isExecuteCountSql) throws HibernateException {
		return (PageCenterStation<?>) getHibernateTemplate().execute(
				new HibernateCallback() {

					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {

						long rowCount = 0;
						if (isExecuteCountSql) {
							SQLQuery countQuery = session
									.createSQLQuery(countSql);
							for (int i = 0; params != null && objs != null
									&& params.length == objs.length
									&& i < params.length; i++) {
								countQuery.setParameter(params[i], objs[i]);
							}

							for (int i = 0; params == null && objs != null
									&& i < objs.length; i++) {
								countQuery.setParameter(i, objs[i]);
							}

							rowCount = ((BigInteger) countQuery.uniqueResult())
									.longValue();
						}

						SQLQuery query = session.createSQLQuery(sql);
						for (int i = 0; params != null && objs != null
								&& params.length == objs.length
								&& i < params.length; i++) {
							query.setParameter(params[i], objs[i]);
						}

						for (int i = 0; params == null && objs != null
								&& i < objs.length; i++) {
							query.setParameter(i, objs[i]);
						}

						if (clazz.equals(Map.class)){
							query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
						}
						else if (clazz.equals(List.class)){
							query.setResultTransformer(Transformers.TO_LIST);
						}
						else{
							Field fields[] = clazz.getDeclaredFields();
							for (Field field : fields) {// 属性及数据类型构造。 如果属性较多，可以巧妙使用循环赛
								if("serialVersionUID".equals(field.getName()))
									continue;
								
								int modifier = field.getModifiers();
								if(Modifier.isPublic(modifier) || Modifier.isProtected(modifier))
									continue;
								
								query.addScalar(field.getName(), TypeFactory.basic(field.getType().getName()));
						    }
							query.setResultTransformer(Transformers.aliasToBean(clazz));
						}
						query.setFirstResult(first);
						query.setMaxResults(max);

						List<Object> list = (List<Object>) query.list();
						return new PageCenterStation<Object>(rowCount, list);
					}
				});
	}

	/**
	 * @see com.xuming.dao.BasePageDao#query(java.lang.String,
	 *      com.xuming.dao.page.Page)
	 */

	public PageObjectSet<T> query(String hql, Page page)
			throws HibernateException {
		return query(hql, null, null, page);
	}

	/**
	 * @see com.xuming.dao.BasePageDao#query(java.lang.String,
	 *      java.lang.Object[], com.xuming.dao.page.Page)
	 */

	public PageObjectSet<T> query(String hql, Object[] args, Page page)
			throws HibernateException {
		return query(hql, null, args, page);
	}

	/**
	 * @see com.xuming.dao.BasePageDao#query(java.lang.String,
	 *      java.lang.String[], java.lang.Object[], com.xuming.dao.page.Page)
	 */
	public PageObjectSet<T> query(final String hql, final String[] params,
			final Object[] args, final Page page) throws HibernateException {
		// 构造分页数据对象
		PageObjectSet<T> pos = null;
		pos = (PageObjectSet<T>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String countHQL = page.getRowCountHQL();
						Query countQuery = session.createQuery(countHQL);
						for (int i = 0; params != null && args != null
								&& params.length != args.length
								&& i < params.length; i++) {
							countQuery.setParameter(params[i], args[i]);
						}

						long count = (Long) countQuery.uniqueResult();

						Query query = session.createQuery(hql);
						for (int i = 0; params != null && args != null
								&& params.length != args.length
								&& i < params.length; i++) {
							query.setParameter(params[i], args[i]);
						}
						query.setFirstResult(page.getFirstRow());
						query.setMaxResults(page.getPageSize());

						PageObjectSet<T> pos = new PageObjectSet<T>();
						List<T> list = (List<T>) query.list();
						pos.setResultList(list);
						pos.setRowCount(count);
						pos.setPageInfo(page);
						return pos;
					}
				});
		return pos;
	}

	public Serializable saveForReturn(Object obj) throws HibernateException,
			Exception {
		try {
			return getHibernateTemplate().save(obj);
		} catch (DataAccessException e) {
			LOG.error("添加信息出错！", e);
			throw new HibernateException(e);
		} catch (Exception e) {
			LOG.error("添加信息出错！", e);
			throw e;
		}
	}

	public PageObjectSet<T> findAllByString(Class<T> clazz, Page page,
			String type, String typeValue) throws HibernateException {

		Criteria criteria = getSession().createCriteria(clazz);
		// 设置查询条件
		if (typeValue != null && type != null && !("").equals(type)
				&& !("").equals(typeValue)) {
			criteria.add(Restrictions.eq(type, typeValue));
		}

		long rowCount = 0;

		int first = page.getFirstRow();
		int max = page.getPageSize();

		criteria.setProjection(Projections.rowCount());
		rowCount = ((Integer) criteria.uniqueResult()).longValue();// 查询获取数据的总量
		criteria.setProjection(null);// 清除criteria对象中的查询函数
		// 设置总记录数
		page.setRowsCount(rowCount);

		criteria.setFirstResult(first);
		criteria.setMaxResults(max);

		List<T> reusltList = (List<T>) criteria.list();

		// 构造分页数据对象
		PageObjectSet<T> pos = new PageObjectSet<T>();
		pos.setResultList(reusltList);
		pos.setPageInfo(page);
		return pos;
	}

	public PageObjectSet findToResult(Class clazz, Criterion[] criterions,
			Page page) throws HibernateException {
		return this.findToResult(clazz, criterions, null, page);
	}

	public PageObjectSet findToResult(Class clazz, Criterion[] criterions,
			Order[] orders, Page page) throws HibernateException {
		Criteria criteria = getSession().createCriteria(clazz);

		// 设置查询条件
		for (int i = 0; criterions != null && i < criterions.length; i++) {
			criteria.add(criterions[i]);
		}

		// 设置排序
		for (int i = 0; orders != null && i < orders.length; i++) {
			criteria.addOrder(orders[i]);
		}

		long rowCount = 0;

		int first = page.getFirstRow();
		int max = page.getPageSize();

		criteria.setProjection(Projections.rowCount());
		rowCount = ((Integer) criteria.uniqueResult()).longValue();// 查询获取数据的总量
		criteria.setProjection(null);// 清除criteria对象中的查询函数
		// 设置总记录数
		page.setRowsCount(rowCount);

		// if (first >= 0 && (max > 0 && max >= first)) {
		criteria.setFirstResult(first);
		criteria.setMaxResults(max);
		// }

		List<Object> reusltList = (List<Object>) criteria.list();

		// 构造分页数据对象
		PageObjectSet<Object> pos = new PageObjectSet<Object>();
		pos.setResultList(reusltList);
		pos.setPageInfo(page);
		return pos;
	}

	public PageObjectSet findToResult(Class clazz, Page page)
			throws HibernateException {
		return this.findToResult(clazz, null, null, page);
	}

	public PageObjectSet queryWithSQL(Class clazz, String sql, Page page)
			throws HibernateException {
		return queryWithSQL(clazz, sql, null, null, page);
	}

	public PageObjectSet queryWithSQL(Class clazz, String sql, Object[] args,
			Page page) throws HibernateException {
		return queryWithSQL(clazz, sql, null, args, page);
	}

	public PageObjectSet queryWithSQL(final Class clazz, final String sql,
			final String[] params, final Object[] objs, final Page page)
			throws HibernateException {
		return (PageObjectSet<Object>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						String countSql = page.getRowCountSQL();
						long rowCount = 0;
						if (CommonUtils.notEmpty(countSql)) {
							SQLQuery countQuery = session
									.createSQLQuery(countSql);
							for (int i = 0; params != null && objs != null
									&& params.length == objs.length
									&& i < params.length; i++) {
								countQuery.setParameter(params[i], objs[i]);
							}

							for (int i = 0;  objs != null
									&& i < objs.length; i++) {
								countQuery.setParameter(i + 1, objs[i]);
							}

							rowCount = ((BigInteger) countQuery.uniqueResult())
									.longValue();
						}

						SQLQuery query = session.createSQLQuery(sql);
						for (int i = 0; params != null && objs != null
								&& params.length == objs.length
								&& i < params.length; i++) {
							query.setParameter(params[i], objs[i]);
						}

						for (int i = 0; objs != null
								&& i < objs.length; i++) {
							query.setParameter(i + 1, objs[i]);
						}

						if (clazz.equals(Map.class))
							query
									.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
						else if (clazz.equals(List.class))
							query.setResultTransformer(Transformers.TO_LIST);
						else
							query.setResultTransformer(Transformers
									.aliasToBean(clazz));
						int first = page.getFirstRow(), max = page
								.getPageSize();

						// if (first >= 0 && (max > 0 && max >= first)) {
						query.setFirstResult(first);
						query.setMaxResults(max);
						// }
						PageObjectSet<Object> pos = new PageObjectSet<Object>();
						pos.setResultList(query.list());
						pos.setRowCount(rowCount);
						pos.setPageInfo(page);
						return pos;
					}
				});
	}

	public List<T> queryWithSQL(Class<T> clazz, String sql,
			Object... values) throws HibernateException {
		return queryWithSQL(clazz, sql, null, values);
	}

	public PageObjectSet<T> query(final String countHQL, final String hql,
			final Object[] args, final int first, final int max)
			throws HibernateException {
		return (PageObjectSet<T>) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException, SQLException {
						Query countQuery = session.createQuery(countHQL);
						for (int i = 0; args != null && i < args.length; i++) {
							countQuery.setParameter(i, args[i]);
						}

						long count = 1;

						Query query = session.createQuery(hql);
						for (int i = 0; args != null && i < args.length; i++) {
							query.setParameter(i, args[i]);
						}
						if (first != -1 && max != -1) {
							query.setFirstResult(first);
							query.setMaxResults(max);
						}

						List<Object> list = (List<Object>) query.list();

						return new PageObjectSet<Object>(count, list);
					}
				});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryPage(java.lang.String, java.lang.String, int, int)
	 */
	public PageCenterStation<T> queryPage(final String countHql, final String queryHql, final int first, final int max) {
		return getHibernateTemplate().execute(new HibernateCallback<PageCenterStation<T>>() {
			public PageCenterStation<T> doInHibernate(Session session) throws HibernateException, SQLException {
				Query countQuery = session.createQuery(countHql);
				long count = (Long)countQuery.uniqueResult();
				
				Query queryQuery = session.createQuery(queryHql);
				if (first >= 0 && max >= 0) {
					queryQuery.setFirstResult(first);
					queryQuery.setMaxResults(max);
				}
				List list = queryQuery.list();
				
				return new PageCenterStation<T>(count, list);
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#findUniqueObject(java.lang.String)
	 */
	public T findUniqueObject(final String hql) {
		return getHibernateTemplate().execute(new HibernateCallback<T>() {
			public T doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				return (T)query.uniqueResult();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryList(java.lang.String)
	 */
	public List<T> queryList(final String hql) {
		return getHibernateTemplate().execute(new HibernateCallback<List<T>>() {
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				return query.list();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryListInMap(java.lang.String)
	 */
	public List<Map> queryListInMap(final String hql) {
		return getHibernateTemplate().execute(new HibernateCallback<List<Map>>() {
			public List<Map> doInHibernate(Session session) throws HibernateException, SQLException {
				Query query = session.createQuery(hql);
				query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
				return query.list();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryCountWithSql(java.lang.String)
	 */
	public long queryCountWithSql(final String sql) {
		return getHibernateTemplate().execute(new HibernateCallback<Long>() {
			public Long doInHibernate(Session session) throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql);
				return Long.valueOf(query.uniqueResult().toString());
			}
		}).longValue();
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryListWithSql(java.lang.String)
	 */
	public List<Object[]> queryListWithSql(final String sql) {
		return getHibernateTemplate().execute(new HibernateCallback<List<Object[]>>() {
			public List<Object[]> doInHibernate(Session session) throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql);
				return query.list();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryListWithSql(java.lang.String, java.lang.Class)
	 */
	public List<T> queryListWithSql(final String sql, final Class<T> clazz) {
		return getHibernateTemplate().execute(new HibernateCallback<List<T>>() {
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
				SQLQuery query = session.createSQLQuery(sql);
				query.setResultTransformer(Transformers.aliasToBean(clazz));
				return query.list();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryListByProcedure(java.lang.String, java.lang.Class, java.lang.Object[])
	 */
	public List<T> queryListByProcedure(final String procedure, final Class<T> clazz, final Object... params) {
		return getHibernateTemplate().execute(new HibernateCallback<List<T>>() {
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
				String call = "{call " + procedure + "(@param)}";
				
				int length = (params == null) ? 0 : params.length;
				if (length > 0) {
					String pn = "?";
					for (int index = 1; index < length; index ++) {
						pn += ", ?";
					}
					call = call.replace("@param", pn);
				} else {
					call = call.replace("@param", "");
				}
				
				SQLQuery query = session.createSQLQuery(call);
				for (int index = 0; index < length; index ++) {
					query.setParameter(index, params[index]);
				}
				
				if (clazz != null) {
					if (Map.class.equals(clazz)) {
						query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
					} else if (List.class.equals(clazz)) {
						query.setResultTransformer(Transformers.TO_LIST);
					} else {
						query.setResultTransformer(Transformers.aliasToBean(clazz));
					}
				}
				return query.list();
			}
		});
	}
	
	/**
	 * @see com.xteam.ecsystem.dao.BaseDao#queryListByProcedure(java.lang.String, java.lang.Object[])
	 */
	public List<T> queryListByProcedure(final String procedure, final Object... params) {
		return getHibernateTemplate().execute(new HibernateCallback<List<T>>() {
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
				String call = "{call " + procedure + "(@param)}";
				
				int length = (params == null) ? 0 : params.length;
				if (length > 0) {
					String pn = "?";
					for (int index = 1; index < length; index ++) {
						pn += ", ?";
					}
					call = call.replace("@param", pn);
				} else {
					call = call.replace("@param", "");
				}
				
				SQLQuery query = session.createSQLQuery(call);
				for (int index = 0; index < length; index ++) {
					query.setParameter(index, params[index]);
				}
				return query.list();
			}
		});
	}
	
	public void queryByProcedure(final String procedure, final Object... params) {
		 getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				String call = "{call " + procedure + "(@param)}";
				
				int length = (params == null) ? 0 : params.length;
				if (length > 0) {
					String pn = "?";
					for (int index = 1; index < length; index ++) {
						pn += ", ?";
					}
					call = call.replace("@param", pn);
				} else {
					call = call.replace("@param", "");
				}
				
				SQLQuery query = session.createSQLQuery(call);
				for (int index = 0; index < length; index ++) {
					query.setParameter(index, params[index]);
				}
				query.executeUpdate();
				return null;
			}
		});
	}
	
	public int queryProcedureForInt(final String procedure, final Object... params) {
		 return getHibernateTemplate().execute(new HibernateCallback<Integer>() {
			public Integer doInHibernate(Session session) throws HibernateException, SQLException {
				// 定义存储过程执行语句
				String call = "{call " + procedure + "(@params)}";
				String pn = "";
				
				// 实参占位符
				for (int i = 0; i < params.length; i++) {
					pn += "?, ";
				}
				
				// 输出参数占位符
				pn = pn + "?";
				call = call.replace("@params", pn);
				
				CallableStatement cs = session.connection().prepareCall(call);
				for (int i = 0; i < params.length; i++) {
					if (params[i] instanceof String) {
						cs.setString(i + 1, params[i].toString());
					}else if (params[i] instanceof Integer) {
						cs.setInt(i + 1, Integer.valueOf(params[i].toString()));
					}else if (params[i] instanceof Double){
						cs.setDouble(i + 1, Double.valueOf(params[i].toString()));
					}else {
						cs.setObject(i + 1, params[i]);
					}
				}
				
				// 注册整形输出参数，和输出参数占位符对应
				cs.registerOutParameter(params.length + 1, Types.INTEGER); 
				cs.execute();
				
				// 获取并返回整形输出参数
				return cs.getInt(params.length + 1);
				
//				CallableStatement cstmt = session.connection().prepareCall("{call take_delivery_goods(?, ?)}");
//				cstmt.setString(1, params[0].toString());
//				cstmt.registerOutParameter(2, Types.INTEGER);
//				cstmt.execute();
//				int i = cstmt.getInt(2);
//				return i;
			}
		});
	}
}
